Previous: Setf Extensions, Up: Generalized Variables [Contents][Index]
This package defines a number of macros that operate on generalized variables. Many are interesting and useful even when the place is just a variable name.
This macro is to setf what
cl-psetq is to setq: When several
places and forms are involved, the
assignments take place in parallel rather than sequentially.
Specifically, all subforms are evaluated from left to right,
then all the assignments are done (in an undefined
order).
This macro increments the number stored in
place by one, or by x if specified. The
incremented value is returned. For example, (cl-incf
i) is equivalent to (setq i (1+ i)), and
(cl-incf (car x) 2) is equivalent to
(setcar x (+ (car x) 2)).
As with setf, care is taken to preserve the
“apparent” order of evaluation. For example,
(cl-incf (aref vec (cl-incf i)))
appears to increment i once, then increment
the element of vec addressed by i;
this is indeed exactly what it does, which means the above
form is not equivalent to the “obvious”
expansion,
(setf (aref vec (cl-incf i))
(1+ (aref vec (cl-incf i)))) ; wrong!
but rather to something more like
(let ((temp (cl-incf i))) (setf (aref vec temp) (1+ (aref vec temp))))
Again, all of this is taken care of automatically by
cl-incf and the other generalized-variable
macros.
As a more Emacs-specific example of cl-incf,
the expression (cl-incf (point) n) is
essentially equivalent to (forward-char
n).
This macro decrements the number stored in place by one, or by x if specified.
This macro inserts x at the front of the list
stored in place, but only if x was not
eql to any existing element of the list. The
optional keyword arguments are interpreted in the same way as
for cl-adjoin. See Lists as Sets.
This macro shifts the places left by one,
shifting in the value of newvalue (which may be
any Lisp expression, not just a generalized variable), and
returning the value shifted out of the first
place. Thus, (cl-shiftf a
b c d) is equivalent
to
(prog1
a
(cl-psetf a b
b c
c d))
except that the subforms of a, b, and c are actually evaluated only once each and in the apparent order.
This macro rotates the places left by one in
circular fashion. Thus, (cl-rotatef a
b c d) is equivalent
to
(cl-psetf a b
b c
c d
d a)
except for the evaluation of subforms.
cl-rotatef always returns nil. Note
that (cl-rotatef a b)
conveniently exchanges a and b.
The following macros were invented for this package; they have no analogues in Common Lisp.
This macro is analogous to let, but for
generalized variables rather than just symbols. Each
binding should be of the form
(place value); the
original contents of the places are saved, the
values are stored in them, and then the body
forms are executed. Afterwards, the
places are set back to their original saved
contents. This cleanup happens even if the forms
exit irregularly due to a throw or an error.
For example,
(cl-letf (((point) (point-min))
(a 17))
…)
moves point in the current buffer to the beginning of the
buffer, and also binds a to 17 (as if by a
normal let, since a is just a
regular variable). After the body exits, a is
set back to its original value and point is moved back to its
original position.
Note that cl-letf on (point) is
not quite like a save-excursion, as the latter
effectively saves a marker which tracks insertions and
deletions in the buffer. Actually, a cl-letf of
(point-marker) is much closer to this behavior.
(point and point-marker are
equivalent as setf places; each will accept
either an integer or a marker as the stored value.)
Since generalized variables look like lists,
let’s shorthand of using
‘foo’ for ‘(foo
nil)’ as a binding would be ambiguous
in cl-letf and is not allowed.
However, a binding specifier may be a
one-element list
‘(place)’, which is
similar to ‘(place
place)’. In other words, the
place is not disturbed on entry to the body, and
the only effect of the cl-letf is to restore the
original value of place afterwards.
Note that in this case, and in fact almost every case,
place must have a well-defined value outside the
cl-letf body. There is essentially only one
exception to this, which is place a plain variable
with a specified value (such as (a
17) in the above example).
This macro is to cl-letf what
let* is to let: It does the
bindings in sequential rather than parallel order.
This is the “generic” modify macro. It calls
function, which should be an unquoted function
name, macro name, or lambda. It passes place and
args as arguments, and assigns the result back to
place. For example, (cl-incf
place n) is the same as
(cl-callf + place n). Some
more examples:
(cl-callf abs my-number) (cl-callf concat (buffer-name) "<" (number-to-string n) ">") (cl-callf cl-union happy-people (list joe bob) :test 'same-person)
Note again that cl-callf is an extension to
standard Common Lisp.
This macro is like cl-callf, except that
place is the second argument of
function rather than the first. For example,
(push x place) is
equivalent to (cl-callf2 cons x
place).
The cl-callf and cl-callf2 macros
serve as building blocks for other macros like
cl-incf, and cl-pushnew. The
cl-letf and cl-letf* macros are used in
the processing of symbol macros; see Macro Bindings.
Previous: Setf Extensions, Up: Generalized Variables [Contents][Index]